package func.study.concurrency.c2;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;

public class Counter {
     private long value = 0;
	public  long getValue() {
		return value;
	}

	public  long increment() {
		if(value == Long.MAX_VALUE) {
			throw new IllegalArgumentException("count overflow");
		}
		return value++;
	}

	public static void main(String[] args) throws InterruptedException {
        test3();
	}
    /**
     * 使用闭锁方式，等所有线程自增完毕后，读取该value值是否正确。
     * 1.如果没有进行同步。有可能读到value < 1200 (有概率)
     * 2.在方法体 getValue 和increment 添加同步。读到的值value==1200
     */
	static void test1() {
        final Counter counter = new Counter();
        final CountDownLatch startLatch = new CountDownLatch(1200);

		for (int i = 0; i < 1200; i++) {
			Thread t = new Thread(() -> {
				counter.increment();
                startLatch.countDown();
            });
			t.start();
		}
        Thread printThread = new Thread(() -> {
            try {
                startLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(counter.getValue());
        });
        printThread.start();
    }

    //使用关卡，来实现，所有线程执行完毕后，进行后置校验
    static void test2() {
        final Counter counter = new Counter();
        CyclicBarrier barrier = new CyclicBarrier(1000, ()->{
            System.out.println(counter.getValue());
        });
        for (int i = 0; i < 1000; i++) {
            Thread t1 = new Thread(() -> {
                counter.increment();
                try {
                    barrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            });
            t1.start();
        }
    }

    //使用2个闭锁来实现，所有线程都初始化完，进行执行递增，所有执行完递增，进行打印
    static void test3() {
        final Counter counter = new Counter();
        CountDownLatch readyLatch = new CountDownLatch(1500); //线程就绪
        CountDownLatch printLatch = new CountDownLatch(1500); //线程开始只能incre 操作闭锁

        for (int i = 0; i < 1500; i++) {
            Thread t = new Thread(() -> {
                readyLatch.countDown();
                try {
                    readyLatch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                counter.increment();
                printLatch.countDown();
            });
            t.start();
        }
        Thread printThread = new Thread(() -> {
            try {
                printLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(counter.getValue());
        });
        printThread.start();


    }



}
